package com.study.seckill.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.study.exceptions.CourseException;
import com.study.exceptions.CourseSeckillException;
import com.study.seckill.dao.CourseSeckillDao;
import com.study.seckill.dao.CourseSeckillMapper;
import com.study.seckill.entity.CourseSeckillES;
import com.study.seckill.es.CourseSeckillRepository;
import com.study.seckill.entity.CourseSeckill;
import com.study.seckill.service.CourseSeckillService;
import com.study.seckill.service.CourseService;
import com.study.seckill.vo.CourseSeckillDetailVO;
import com.study.util.ResponseResult;
import com.study.vo.CourseInfoVO;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @ClassName: CourseSeckillServiceImpl
 * @Author: wYin
 * @Date: 2022/3/10 14:41
 */
@Service
public class CourseSeckillServiceImpl extends ServiceImpl<CourseSeckillMapper, CourseSeckill> implements CourseSeckillService {

    @Autowired
    private CourseSeckillDao courseSeckillDao;

    @Autowired
    private CourseSeckillMapper courseSeckillMapper;

    @Autowired
    private CourseService courseService;

    @Autowired
    private CourseSeckillRepository courseSeckillRepository;

    @Override
    public List<CourseSeckill> showCourseSeckill() {
        return courseSeckillMapper.getShowCourseSeckill();
    }

    @Override
    public CourseSeckill add(CourseSeckill courseSeckill) {
        long time = new Date().getTime();
        //添加版本信息
        courseSeckill.setVersion(String.valueOf(time));
        ResponseResult<CourseInfoVO> courseInfoVOResponseResult = courseService.getById(courseSeckill.getCourseId());
        CourseInfoVO data = courseInfoVOResponseResult.getData();
        BigDecimal price = data.getPrice();
        BigDecimal seckillPrice = courseSeckill.getSeckillPrice();
        BigDecimal subtract = price.subtract(seckillPrice);
        courseSeckill.setFavorablePrice(subtract);
        CourseSeckill save = courseSeckillDao.save(courseSeckill);
        //添加到elasticsearch中
        CourseSeckillES courseSeckillES = new CourseSeckillES();
        courseSeckillES.setId(save.getId());
        courseSeckillES.setName(save.getName());
        courseSeckillES.setCourse_id(save.getCourseId());
        courseSeckillES.setShow_time(save.getShowTime());
        courseSeckillES.setStart_time(save.getStartTime());
        courseSeckillES.setEnd_time(save.getEndTime());
        courseSeckillES.setSeckill_price(save.getSeckillPrice());
        courseSeckillES.setFavorable_price(save.getFavorablePrice());
        courseSeckillES.setSeckill_num(save.getSeckillNum());
        courseSeckillES.setVersion(save.getVersion());
        CourseSeckillES save1 = courseSeckillRepository.save(courseSeckillES);
        return save;
    }

    /**
     * @Desc: 根据传入的秒杀id和秒杀数量更新秒杀的库存
     * @Param: [courseSeckill]
     * @Return: boolean
     * @Author: wYin
     * @Time: 2022/3/14 10:03
     */
    @Override
    @Transactional
    public boolean updateSeckillStock(CourseSeckill courseSeckill){
        //根据秒杀的id查询
        CourseSeckill courseSeckill1 = courseSeckillMapper.selectById(courseSeckill.getId());
        if(courseSeckill1==null){
            throw new CourseException("没有查询到当前描述课程");
        }
        //更新订单
        boolean result = courseSeckillMapper.updateSeckillStock(courseSeckill.getId(),courseSeckill1.getVersion());
        if(!result){
            throw new CourseException("更新失败");
        }
        return  true;
    }

    @Override
    public CourseSeckillDetailVO getSeckillInfoById(Integer id) {
        //根据id查询秒杀信息
        CourseSeckill courseSeckill = courseSeckillMapper.selectById(id);
        if(courseSeckill==null){
            throw new CourseSeckillException("未查询到当前秒杀的信息");
        }
        //根据秒杀的信息查询课程的信息
        ResponseResult<CourseInfoVO> courseInfoVO = courseService.getById(courseSeckill.getCourseId());
        if(courseInfoVO.getCode()!=200){
            throw new CourseException("未查询到该商品信息");
        }
        CourseSeckillDetailVO courseSeckillDetailVO = new CourseSeckillDetailVO();
        courseSeckillDetailVO.setCourseSeckill(courseSeckill);
        courseSeckillDetailVO.setCourseInfoVO(courseInfoVO.getData());
        return courseSeckillDetailVO;
    }


    @Autowired
    private ElasticsearchRestTemplate elasticsearchTemplate;
    @Override
    public List<CourseSeckillES> getByName(String name) {
        List<CourseSeckillES> courseSeckills = new ArrayList<>();
//        需要查询的字段
        MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("name", name);
        //构建高亮查询
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(matchQueryBuilder)
                .withHighlightFields(
                        new HighlightBuilder.Field("name"))
                .withHighlightBuilder(new HighlightBuilder().preTags("<span style='color:red'>").postTags("</span>"))
                .build();
        //查询
        SearchHits<CourseSeckillES> search = elasticsearchTemplate.search(searchQuery, CourseSeckillES.class);
        //得到查询返回的内容
        List<SearchHit<CourseSeckillES>> searchHits = search.getSearchHits();
        //遍历返回的内容进行处理
        for(SearchHit<CourseSeckillES> searchHit:searchHits){
            //高亮的内容
            Map<String, List<String>> highlightFields = searchHit.getHighlightFields();
            //将高亮的内容填充到content中
            searchHit.getContent().setName(highlightFields.get("name")==null ? searchHit.getContent().getName():highlightFields.get("name").get(0));
            //放到实体类中
            courseSeckills.add(searchHit.getContent());
        }

        return courseSeckills;
    }
}
